package com.jx.mst.mst.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jx.mst.model.common.dtos.PageParams;
import com.jx.mst.model.common.dtos.ResponseResult;
import com.jx.mst.model.mst.dtos.MstSelInfoDtos;
import com.jx.mst.model.mst.entity.MstInfoModel;
import com.jx.mst.model.mst.reps.MstSelReps;
import com.jx.mst.mst.dao.MstSelDao;
import com.jx.mst.mst.entity.MstInfo;
import com.jx.mst.mst.entity.MstSel;
import com.jx.mst.mst.service.MstInfoService;
import com.jx.mst.mst.service.MstSelService;
import jakarta.annotation.Resource;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.jx.mst.model.common.redisCon.MseRedisCon.*;

/**
 * 面试题分类(MstSel)表服务实现类
 *
 * @author makejava
 * @since 2023-12-25 07:13:11
 */
@Service("mstSelService")
public class MstSelServiceImpl extends ServiceImpl<MstSelDao, MstSel> implements MstSelService {

    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    RedissonClient redissonClient;
    @Resource
    private MstInfoService mstInfoService;
    @Override
    public ResponseResult queryByPage(PageParams pageParams) {
        PageHelper.startPage(pageParams.getPageNum(), pageParams.getPageSize());
//        List<UsUser> list = usUserService.query().orderByDesc("update_time").like(StrUtil.isNotBlank(name), "user_name", name).like(StrUtil.isNotBlank(phone), "user_phone", phone).eq("user_level",USER_LEVEL_ADMIN).list();
        List<MstSel> list = query().orderByAsc("mst_sel_sort").like(StrUtil.isNotBlank(pageParams.getKey()), "mst_sel_name", pageParams.getKey()).list();
        PageInfo page = new PageInfo(list);
        return ResponseResult.okResult(page);
    }

    @Override
    public List<MstSelReps> getHomeMstSel() {

        String jsonData = stringRedisTemplate.opsForValue().get(REDIS_HOME_CACHED_MSTSEL);
        if(StrUtil.isNotBlank(jsonData)){
            List<MstSelReps> list = JSONUtil.toList(jsonData, MstSelReps.class);
            return list;
        }
        if(jsonData!=null){
            return new ArrayList<>();
        }
        RLock lock = redissonClient.getLock(REDIS_HOME_LOCK_MSTSEL);
        try {
            boolean flag = lock.tryLock(1, TimeUnit.MILLISECONDS);
            if(!flag){
               Thread.sleep(5000);
                getHomeMstSel();
            }
//            Set<ZSetOperations.TypedTuple<String>> tuples = stringRedisTemplate.opsForZSet().rangeWithScores(REDIS_ZSET_MSTSEL, 0, -1);
//            Set<ZSetOperations.TypedTuple<String>> tuples = stringRedisTemplate.opsForZSet().rangeWithScores(REDIS_ZSET_MSTSEL, 0, -1);
//            Set<String> strings = stringRedisTemplate.opsForZSet().reverseRangeByScore(REDIS_ZSET_MSTSEL, 0, 9999999);
//            List<MstSelReps> collect = tuples.stream().map(item -> {
//                String value = item.getValue();
//                MstSel mstSel = getById(value);
//                MstSelReps mstSelReps = BeanUtil.copyProperties(mstSel, MstSelReps.class);
//                String str = stringRedisTemplate.opsForValue().get(REDIS_PREX_MSTSEL + mstSel.getId());
//                mstSelReps.setCount(str);
//                return mstSelReps;
//            }).limit(6).collect(Collectors.toList());
//            if(collect.isEmpty()){
//                stringRedisTemplate.opsForValue().set(REDIS_HOME_CACHED_MSTSEL,"",30, TimeUnit.MINUTES);
//            }else {
//                JSONObject jsonObject = JSONUtil.parseObj(collect);
//                stringRedisTemplate.opsForValue().set(REDIS_HOME_CACHED_MSTSEL,jsonObject.toString(),30, TimeUnit.MINUTES);
//            }
//            Double score = stringRedisTemplate.opsForZSet().score(REDIS_ZSET_MSTSEL.toString(), String.valueOf(4));
//            Long rank2 = stringRedisTemplate.opsForZSet().score(REDIS_ZSET_MSTSEL.toString(),  String.valueOf(6));

            Set<String> strings = stringRedisTemplate.opsForZSet().reverseRangeByScore(REDIS_ZSET_MSTSEL, Double.MIN_VALUE, Double.MAX_VALUE);
            List<MstSelReps> collect = strings.stream().map(item -> {
                MstSel mstSel = getById(item);
                MstSelReps mstSelReps = BeanUtil.copyProperties(mstSel, MstSelReps.class);
                String s = stringRedisTemplate.opsForValue().get(REDIS_PREX_MSTSEL + mstSel.getId());
                mstSelReps.setCount(s);
                Double score = stringRedisTemplate.opsForZSet().score(REDIS_ZSET_MSTSEL.toString(), item);
                int scores = (int) Math.round(score);
                mstSelReps.setHits(scores);
                return mstSelReps;
            }).limit(6).collect(Collectors.toList());
            if(collect.isEmpty()){
                stringRedisTemplate.opsForValue().set(REDIS_HOME_CACHED_MSTSEL,"",30, TimeUnit.MINUTES);
            }else {
//                JSONObject jsonObject = JSONUtil.parseObj(collect);
                JSONArray objects = JSONUtil.parseArray(collect);
                stringRedisTemplate.opsForValue().set(REDIS_HOME_CACHED_MSTSEL,objects.toString(),30, TimeUnit.MINUTES);
            }

            return collect;
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }
    }

    @Override
    public List<MstSel> getMstselList() {
        String cachedstr = stringRedisTemplate.opsForValue().get(REDIS_MSTSEL_CACHED_MSTSEL);
        if(StrUtil.isNotBlank(cachedstr)){
            List<MstSel> list = JSONUtil.toList(cachedstr, MstSel.class);
            return list;
        }
        if(cachedstr!=null){
            return new ArrayList<>();
        }
        List<MstSel> list = new ArrayList<>();
        RLock lock = redissonClient.getLock(REDIS_MSTSEL_LOCK_MSTSEL);
        try {
            boolean flag = lock.tryLock(1, TimeUnit.MILLISECONDS);
            if(!flag){
                Thread.sleep(500);
                getMstselList();
            }
            list = query().orderByAsc("mst_sel_sort").list();
            if(list.isEmpty()){
                stringRedisTemplate.opsForValue().set(REDIS_MSTSEL_CACHED_MSTSEL,"",30,TimeUnit.MINUTES);
            }else {
                JSONArray objects = JSONUtil.parseArray(list);
                stringRedisTemplate.opsForValue().set(REDIS_MSTSEL_CACHED_MSTSEL,objects.toString(),30,TimeUnit.MINUTES);
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }

        return list;
    }

    @Override
    public MstSelInfoDtos getMstelandMstinfoByMstselId(String mstselId) {
        if(mstselId.equals("0")){
//            MstSelInfoDtos mstSelInfoDtos = new MstSelInfoDtos();
            MstSelInfoDtos mstelandMstinfoByZero = getMstelandMstinfoByZero();
            return mstelandMstinfoByZero;
        }

        String cachedstr = stringRedisTemplate.opsForValue().get(REDIS_MSTSEL_CACHED_MSTINFOLIST + mstselId);
        if(StrUtil.isNotBlank(cachedstr)){
//            MstSelInfoDtos bean = BeanUtil.toBean(cachedstr, MstSelInfoDtos.class);
            MstSelInfoDtos bean = JSONUtil.toBean(cachedstr, MstSelInfoDtos.class);
            return bean;
        }
        if(cachedstr!=null){
            return new MstSelInfoDtos();
        }


        RLock lock = redissonClient.getLock(REDIS_MSTSEL_LOCK_MSTINFOLIST+mstselId);
        MstSelInfoDtos mstSelInfo = new MstSelInfoDtos();
        try {
            boolean flag = lock.tryLock(1, TimeUnit.MILLISECONDS);
            if(!flag){
                Thread.sleep(500);
                getMstelandMstinfoByMstselId(mstselId);
            }
            MstSel mstSel = getById(mstselId);
            if(mstSel==null){
                stringRedisTemplate.opsForValue().set(REDIS_MSTSEL_CACHED_MSTINFOLIST+mstselId,"",30,TimeUnit.MINUTES);
            }else {
                mstSelInfo = BeanUtil.copyProperties(mstSel, MstSelInfoDtos.class);
                if(!mstselId.equals("0")){
                    List<MstInfo> list = mstInfoService.query().eq(!mstselId.equals("0"), "mst_sel_id", mstselId).list();
                    List<MstInfoModel> collect = list.stream().map(item -> {
                        MstInfoModel mstInfoModel = BeanUtil.copyProperties(item, MstInfoModel.class);

                        Double score = stringRedisTemplate.opsForZSet().score(REDIS_ZSET_MSTINFO.toString(), item.getId().toString());
                        int scores = (int) Math.round(score);
                        mstInfoModel.setHits(scores);

                        return mstInfoModel;
                    }).collect(Collectors.toList());
                    mstSelInfo.setMstinfoList(collect);
                }
                JSONObject jsonObject = JSONUtil.parseObj(mstSelInfo);
                stringRedisTemplate.opsForValue().set(REDIS_MSTSEL_CACHED_MSTINFOLIST+mstselId,jsonObject.toString(),30,TimeUnit.MINUTES);
            }

        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }

        return mstSelInfo;
    }

    private MstSelInfoDtos getMstelandMstinfoByZero() {
        String cachedstr = stringRedisTemplate.opsForValue().get(REDIS_MSTSEL_CACHED_MSTINFOLIST + "0");
        if(StrUtil.isNotBlank(cachedstr)){
//            MstSelInfoDtos bean = BeanUtil.toBean(cachedstr, MstSelInfoDtos.class);
            MstSelInfoDtos bean = JSONUtil.toBean(cachedstr, MstSelInfoDtos.class);
            return bean;
        }
        if(cachedstr!=null){
            return new MstSelInfoDtos();
        }


        RLock lock = redissonClient.getLock(REDIS_MSTSEL_LOCK_MSTINFOLIST+"0");
        MstSelInfoDtos mstSelInfo = new MstSelInfoDtos();
        try {
            boolean flag = lock.tryLock(1, TimeUnit.MILLISECONDS);
            if(!flag){
                Thread.sleep(500);
                getMstelandMstinfoByMstselId("0");
            }
            MstSel mstSel = new MstSel();
            mstSel.setMstSelName("50道面试题");
            mstSel.setId(0L);
            mstSel.setMstSelDes("50道面试题");
            if(mstSel==null){
                stringRedisTemplate.opsForValue().set(REDIS_MSTSEL_CACHED_MSTINFOLIST+"0","",30,TimeUnit.MINUTES);
            }else {
                mstSelInfo = BeanUtil.copyProperties(mstSel, MstSelInfoDtos.class);
                    List<MstInfo> list = mstInfoService.query().list();
                    List<MstInfoModel> collect = list.stream().map(item -> {
                        MstInfoModel mstInfoModel = BeanUtil.copyProperties(item, MstInfoModel.class);
                        Double score = stringRedisTemplate.opsForZSet().score(REDIS_ZSET_MSTINFO.toString(), item.getId().toString());
                        int scores = (int) Math.round(score);
                        mstInfoModel.setHits(scores);
                        return mstInfoModel;
                    }).limit(50).collect(Collectors.toList());
                    mstSelInfo.setMstinfoList(collect);

                JSONObject jsonObject = JSONUtil.parseObj(mstSelInfo);
                stringRedisTemplate.opsForValue().set(REDIS_MSTSEL_CACHED_MSTINFOLIST+"0",jsonObject.toString(),30,TimeUnit.MINUTES);
            }

        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }

        return mstSelInfo;
    }


}

